package org.dromara.app.controller.app;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
import lombok.RequiredArgsConstructor;
import org.dromara.app.domain.bo.AppUserBo;
import org.dromara.app.domain.vo.AppUserVo;
import org.dromara.app.service.AppUserService;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * App端用户信息
 *
 * @author ruoyi
 */
@Tag(name = "App用户管理", description = "App端用户信息管理接口")
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/user")
public class AppUserController extends BaseController {

    private final AppUserService appUserService;

    /**
     * 查询App端用户信息列表
     */
    @Operation(summary = "查询用户列表", description = "分页查询App端用户信息列表")
    @SaCheckPermission("app:user:list")
    @GetMapping("/list")
    public TableDataInfo<AppUserVo> list(
        @Parameter(description = "查询条件") @Valid AppUserBo bo, 
        @Parameter(description = "分页参数") @Valid PageQuery pageQuery) {
        return appUserService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出App端用户信息列表
     */
    @Operation(summary = "导出用户列表", description = "导出App端用户信息到Excel")
    @SaCheckPermission("app:user:export")
    @Log(title = "App端用户信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(
        @Parameter(description = "查询条件") @Valid AppUserBo bo, 
        HttpServletResponse response) {
        List<AppUserVo> list = appUserService.queryList(bo);
        ExcelUtil.exportExcel(list, "App端用户信息", AppUserVo.class, response);
    }

    /**
     * 获取App端用户信息详细信息
     */
    @Operation(summary = "获取用户详情", description = "根据用户ID获取详细信息")
    @SaCheckPermission("app:user:query")
    @GetMapping("/{userId}")
    public R<AppUserVo> getInfo(
        @Parameter(description = "用户ID", required = true) 
        @PathVariable @NotNull(message = "用户ID不能为空") @Positive(message = "用户ID必须为正数") Long userId) {
        return R.ok(appUserService.queryById(userId));
    }

    /**
     * 新增App端用户信息
     */
    @Operation(summary = "新增用户", description = "创建新的App端用户")
    @SaCheckPermission("app:user:add")
    @Log(title = "App端用户信息", businessType = BusinessType.INSERT)
    @PostMapping()
    public R<Void> add(
        @Parameter(description = "用户信息", required = true) 
        @Validated(AddGroup.class) @RequestBody AppUserBo bo) {
        return toAjax(appUserService.insertByBo(bo));
    }

    /**
     * 修改App端用户信息
     */
    @Operation(summary = "修改用户", description = "更新App端用户信息")
    @SaCheckPermission("app:user:edit")
    @Log(title = "App端用户信息", businessType = BusinessType.UPDATE)
    @PutMapping()
    public R<Void> edit(
        @Parameter(description = "用户信息", required = true) 
        @Validated(EditGroup.class) @RequestBody AppUserBo bo) {
        return toAjax(appUserService.updateByBo(bo));
    }

    /**
     * 删除App端用户信息
     */
    @Operation(summary = "删除用户", description = "批量删除App端用户")
    @SaCheckPermission("app:user:remove")
    @Log(title = "App端用户信息", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public R<Void> remove(
        @Parameter(description = "用户ID列表", required = true) 
        @PathVariable @NotEmpty(message = "用户ID列表不能为空") Long[] userIds) {
        return toAjax(appUserService.deleteWithValidByIds(List.of(userIds), true));
    }

    /**
     * 重置密码
     */
    @Operation(summary = "重置密码", description = "重置用户密码")
    @SaCheckPermission("app:user:resetPwd")
    @Log(title = "App端用户信息", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public R<Void> resetPwd(
        @Parameter(description = "用户信息", required = true) 
        @Validated(EditGroup.class) @RequestBody AppUserBo bo) {
        return toAjax(appUserService.resetPassword(bo.getUserId(), bo.getPassword()));
    }

    /**
     * 状态修改
     */
    @Operation(summary = "修改用户状态", description = "启用或禁用用户")
    @SaCheckPermission("app:user:edit")
    @Log(title = "App端用户信息", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public R<Void> changeStatus(
        @Parameter(description = "用户信息", required = true) 
        @Validated(EditGroup.class) @RequestBody AppUserBo bo) {
        // 如果用户状态变为禁用，则冻结用户的所有token
        if ("1".equals(bo.getStatus())) {
            StpUtil.disable(bo.getUserId(), -1); // -1表示永久冻结，直到手动解冻
        } else if ("0".equals(bo.getStatus())) {
            // 如果用户状态变为正常，则解冻用户
            StpUtil.untieDisable(bo.getUserId());
        }
        return toAjax(appUserService.updateUserStatus(bo.getUserId(), bo.getStatus()));
    }

    /**
     * 根据用户编号获取详细信息
     */
    @Operation(summary = "获取用户档案", description = "根据用户ID获取用户档案信息")
    @SaCheckPermission("app:user:query")
    @GetMapping("/profile/{userId}")
    public R<AppUserVo> profile(
        @Parameter(description = "用户ID", required = true) 
        @PathVariable @NotNull(message = "用户ID不能为空") @Positive(message = "用户ID必须为正数") Long userId) {
        AppUserVo user = appUserService.queryById(userId);
        return R.ok(user);
    }

    /**
     * 获取当前用户信息
     */
    @Operation(summary = "获取当前用户信息", description = "获取当前登录用户的详细信息")
    @GetMapping("/getInfo")
    public R<AppUserVo> getInfo() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        AppUserVo user = appUserService.queryById(loginUser.getUserId());
        return R.ok(user);
    }

    /**
     * 获取用户个人信息
     */
    @Operation(summary = "获取个人信息", description = "获取当前用户的个人信息")
    @GetMapping("/profile")
    public R<AppUserVo> getUserProfile() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        AppUserVo user = appUserService.queryById(loginUser.getUserId());
        return R.ok(user);
    }

    /**
     * 修改用户个人信息
     */
    @Operation(summary = "修改个人信息", description = "更新当前用户的个人信息")
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/profile")
    public R<Void> updateUserProfile(
        @Parameter(description = "用户信息", required = true) 
        @Validated(EditGroup.class) @RequestBody AppUserBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setUserId(loginUser.getUserId());
        return toAjax(appUserService.updateByBo(bo));
    }


    /**
     * 重置密码
     */
    @Operation(summary = "修改密码", description = "修改当前用户的登录密码")
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/profile/updatePwd")
    public R<Void> updateUserPwd(
        @Parameter(description = "原密码", required = true) 
        @RequestParam @NotBlank(message = "原密码不能为空") @Size(min = 6, max = 20, message = "密码长度必须在6-20位之间") String oldPassword,
        @Parameter(description = "新密码", required = true) 
        @RequestParam @NotBlank(message = "新密码不能为空") @Size(min = 6, max = 20, message = "密码长度必须在6-20位之间") String newPassword) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        return toAjax(appUserService.updatePassword(loginUser.getUserId(), oldPassword, newPassword));
    }

}